home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programmierung
/
Power-Programmierung (Tewi)(1994).iso
/
magazine
/
progjour
/
1991
/
06
/
editor.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-10-02
|
31KB
|
934 lines
/* edit.c-- Low-Level Workhorse Functions */
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <ctype.h>
#include <dos.h>
#include <conio.h>
#include <string.h>
#include <tools/viewport.h>
#include <tools/textbuf.h>
#include <tools/window.h>
/* Interface functions to test the edit engine. They are described
* in engine.h
*
* These functions are used internally, they do not interface
* with the edit engine:
*/
static int draw (win *const p, int ask_top, int ask_left );
static int hscroll (win *const p, int left);
static int bottom (win *const p, int offset);
static int del_line(win *const p, textbuf *const b,int which_line);
static int export (win *const p, textbuf *const b,int which_line);
static void status (win *const p, char *fmt, ... );
/*------------------------------------------------------------*/
int e_open( win *const this )
{
/* Called when engine for a specific window is opened.
* Try to initialize buffer by importing the top few lines.
* On the first call, the import function should take care
* of both opening the file and adjusting this->bottom to hold
* the line number of the bottom line in the file. It should
* set up the line-number table at this time, as well.
*/
textbuf *b = &this->b;
int nrows = b_nrows(b);
int row, i;
char *new_line;
if( this->import )
{
for( row = 0; row < nrows; ++row )
{
if( !(new_line = (*this->import)(this,row)) )
break;
bottom( this, +1 );
b_gotorc(b, row, 0);
for( i = b_ncols(b); --i >= 0 && *new_line ;)
*b_advance(b) = *new_line++;
}
e_gotorc(this,0,0);
draw (this,0,0);
}
return 1;
}
/*------------------------------------------------------------*/
int e_close( win *const this )
{
/* Prepare for closing the window. Save the window state by
* exporting the current buffer and various important offsets.
* This function may be called several times.
*/
textbuf *b = &this->b;
viewport *v = &this->v;
int nrows = b_nrows(b);
int row;
if( this->export )
{
for( row = 0; row < nrows && row <= this->bottom; ++row )
{
b_gotorc(b, row, 0);
if( !export( this, b, this->file_off + row ) )
break;
}
status( this, "%%%% row, viewport = %d %%%%",v_row(v) );
status( this, "%%%% col, viewport = %d %%%%",v_col(v) );
status( this, "%%%% row, offset = %d %%%%",this->row_off );
status( this, "%%%% col, offset = %d %%%%",this->col_off );
status( this, "%%%% file offset = %d %%%%",this->file_off);
}
return 1;
}
/*------------------------------------------------------------
* Little stuff:
* e_vrow Current viewport row (top == 0).
* e_vcol Current viewport column (left == 0).
* e_vnrows Number of rows in viewport.
* e_vncols Number of columns in viewport.
* e_isword True if c argument is a "word".
* e_maxrow Largest virtual (file) row index
* e_maxcol Largest virtual (file and buffer) column index
* e_col Current virtual (file and buffer) cursor column
* e_row Current virtual (file) cursor row
* e_cur Character at current cursor position.
* e_last Index of rightmost nonwhite character on line,
* zero if the line is blank.
*/
#pragma warn -par /* turn off warnings about arguments not used */
int e_vrow (win *const w) { return v_row (&w->v); }
int e_vcol (win *const w) { return v_col (&w->v); }
int e_vnrows (win *const w) { return v_nrows (&w->v); }
int e_vncols (win *const w) { return v_ncols (&w->v); }
int e_isword (win *const w,
int c) { return( isalnum(c) || c=='_' );}
int e_maxrow (win *const w) { return w->bottom; }
int e_maxcol (win *const w) { return b_ncols(&w->b) -1; }
int e_col (win *const w) { return b_col(&w->b); }
int e_row (win *const w) { return b_row(&w->b)
+ w->file_off;}
int e_cur (win *const w) { return *b_current(&w->b); }
int e_last (win *const w) { return b_last(&w->b); }
#pragma warn +par
/*------------------------------------------------------------
* e_attention() and e_error();
*
* e_attention() rings the bell if not a horizontal motion. In
* any event it sets the window's error flag.
* e_error() returns the value of the flag and resets the
* flag to zero.
*/
void e_attention(win *const this, int h)
{
if(!h)
putchar('\a');
this->error = 1;
}
int e_error( win *const this )
{
int rv = this->error;
this->error = 0;
return rv;
}
/*------------------------------------------------------------*/
int e_first (win *const this)
{
// Return the column index of the first nonwhite character
// on the current line or 0 if the line is blank
textbuf *const b = &this->b;
int start_col = b_col(b);
int start_row = b_row(b);
int last_col = b_ncols(b) - 1;
int col;
b_gotorc(b, start_row, 0);
for( col = 0; (col<last_col) && isspace(*b_current(b)); )
{
++col;
b_advance(b);
}
if( isspace(*b_current(b)) ) /* line was entirely blank */
col = 0;
b_gotorc( b, start_row, start_col );
return col;
}
/*------------------------------------------------------------*/
int e_find_c(win *const this, int c, int forward, int incl)
{
/* If the character is found on the current line (to the
* right of the current cursor position if "forward" is true,
* to the left otherwise) return the column index of c.
* Otherwise return -1. If "incl" is false, return the index
* of the character next to the c rather than the index of
* c itself.
*/
textbuf *b = &this->b;
int row = b_row(b);
int col = b_col(b);
int last = b_last(b);
int start_col = col;
int rv = -1;
if( forward ) forward = 1;
else forward = -1;
col += forward; /* start search at least one column */
if( !incl ) /* away if not inclusive, add one more */
col += forward;
if( !(0 <= col && col <= last) ) /* col isn't on the line */
rv = -1;
else
{
b_gotorc(b, row, col);
while( *b_current(b) != c && !b_ateol(b) )
{
col += forward;
b_gotorc(b, row, col);
}
rv = (*b_current(b) == c) ? col : -1 ;
if(rv != -1 && !incl) /* if not including, */
if( (rv -= forward) < 0 ) /* back up a notch */
rv = -1;
b_gotorc(b, row, start_col);
}
return rv;
}
/*------------------------------------------------------------*/
static void status( win *const this, char *fmt, ... )
{
/* works like fprintf, but outputs string using the
* current window's export function. String is exported as
* line -1.
*/
char scratch[W_LINEMAX];
va_list args;
int len;
if( this->export )
{
va_start(args, fmt);
len = vsprintf(scratch, fmt, args);
va_end(args);
(*this->export)( this, -1, scratch, len+1, len );
}
}
/*---------------------------------------------------------------*/
static int export( win *const this,textbuf *const b,int which_line)
{
/* Export current buffer-cursor line as line which_line,
* cursor does not move.
*/
int row = b_row(b);
int col = b_col(b);
char scratch[W_LINEMAX];
char *p;
int i;
if( this->export )
{
b_gotorc(b,row,0);
for(p=scratch, i=b_ncols(b); --i >= 0; )
*p++ = *b_advance(b);
b_gotorc(b,row,col);
(*this->export)( this, which_line, scratch, b_ncols(b),
b_last (b)+1);
return 1;
}
return 0;
}
/*------------------------------------------------------------*/
static int del_line( win *const this, textbuf *const b,
int which_line )
{
/* export current buffer-cursor line for delete, cursor */
/* does not move. */
int row = b_row(b);
int col = b_col(b);
char scratch[W_LINEMAX];
char *p;
int i;
if( this->remove )
{
b_gotorc(b,row,0);
for(p=scratch, i=b_ncols(b); --i >= 0; )
*p++ = *b_advance(b);
b_gotorc(b,row,col);
(*this->remove)( this, which_line, scratch,
b_ncols(b), b_last(b)+1);
return 1;
}
return 0;
}
/*------------------------------------------------------------*/
int e_vscroll( win *const this, int up, int import )
{
/* Scroll text up one line if if up > 0, down otherwise. If
* import is true, the scroll won't happen unless a new top
* or bottom line can be imported from the overflow file. If
* it's false, the scroll always happens, no attempt is made
* to do an import, and the bottom (or top) line will be
* filled with blanks. Return true on success, false
* otherwise.
*/
viewport *const v = &this->v ;
textbuf *const b = &this->b ;
int rv = 1; /* return value */
int brow = b_row(b); /* buffer row/column */
int bcol = b_col(b);
int vrow = v_row(v); /* viewport row/column */
int vcol = v_col(v);
int i;
char *new_line;
if( up > 0 ) /* Move text up, viewport moves down */
{ /* relative to buffer */
if( (this->row_off + v_nrows(v)) < b_nrows(b) )
{
/* Viewport isn't banged up against bottom of
* buffer. Slide viewport over text, but don't have
* to modify buffer. Position buffer cursor at left
* edge of line with which to fill the viewport's
* opened up bottom line: the buffer line corres-
* ponding to the one just below the viewport.
* Slide the viewport by incrementing row_off.
*/
b_gotorc(b, this->row_off+v_nrows(v), this->col_off);
++this->row_off;
}
else if( !import ) /* import is suppressed */
{
new_line = ""; /* pretend we got an empty line */
goto got_bot;
}
else if( !this->import ) /* try to import bottom line */
{
rv = 0; /* no import function */
goto exit;
}
else if( (i = this->file_off + b_nrows(b)) > this->bottom )
{
rv = 0; /* line doesn't exist */
goto exit;
}
else if( !(new_line = (*this->import)(this,i)) )
{
rv = 0; /* couldn't import it */
goto exit;
}
else /* got the line, add it to the buffer & viewport */
{
got_bot:
b_gotorc(b, 0, 0); /* export the top line */
export (this, b, this->file_off );
++this->file_off ;
b_closedown (b, ' '); /* delete top line and move */
/* following text up. */
b_gotorc(b, b_nrows(b)-1, 0); /* buffer=new last line */
for( i = b_ncols(b); --i >= 0 && *new_line ;)
*b_advance(b) = *new_line++;
b_gotorc(b, b_nrows(b)-1, 0); /* Cursor to line start */
--brow; /* make cursor track previous position */
}
/* Scroll the viewport text up one line, then copy the
* associated text for the bottom line from the buffer
* to the viewport.
*/
if( !this->update )
{
if( vrow == 0 ) /* Old line is gone */
{
/* col of new top line */
b_gotorc(b, this->row_off, bcol);
}
else
b_gotorc(b, brow, bcol );
}
else
{
v_scroll(v, 1, 0); /* scroll up one line */
v_gotorc(v, v_nrows(v)-1, 0); /* last line, column 0 */
/* copy buffer to screen */
for(i = v_ncols(v); --i >= 0 ;)
v_putc(v, *b_advance(b), 1 );
if( vrow == 0 ) /* Old line is gone */
{ /* can't restore cursor */
b_gotorc(b, this->row_off, bcol);
v_gotorc(v, 0, vcol);
}
else /* restore original cursor position */
{
b_gotorc(b, brow, bcol );
v_gotorc(v, vrow-1, vcol );
}
}
}
else /* Move text down, viewport moves up */
{ /* relative to buffer */
if( this->row_off > 0 )
{
/* Viewport isn't banged up against top of buffer.
* Slide viewport over text. Position buffer cursor
* at left edge of line with which to fill the
* viewport's opened-up top line. Note that b_gotorc()
* has side effects so the -- must be done separately.
*/
--this->row_off;
b_gotorc(b, this->row_off, this->col_off );
}
else if( this->file_off <= 0 )
{
rv = 0; /* may not scroll past initial top line */
goto exit;
}
else if( !import ) /* import is suppressed */
{
new_line = ""; /* pretend we got an empty line */
goto got_top;
}
else if(!this->import ) /* try to import new top line */
{
rv = 0; /* No import function */
goto exit;
}
else if( this->file_off <= 0 )
{
rv = 0; /* Line doesn't exist */
goto exit;
}
else if(!(new_line=(*this->import)(this,this->file_off-1)))
{
rv = 0; /* Couldn't import new line */
goto exit;
}
else /* got the line, add it to the buffer & viewport */
{
got_top:
--this->file_off;
b_gotorc (b, b_nrows(b)-1, 0); /* export bottom line */
export (this, b, this->file_off + b_nrows(b) );
b_closeup (b, ' ' ); /* delete bottom line */
b_gotorc(b, 0, 0); /* buffer = new top line */
for( i = b_ncols(b); --i >= 0 && *new_line ;)
*b_advance(b) = *new_line++;
b_gotorc(b, 0, 0); /* Cursor to start of new line */
++brow; /* cursor tracks previous position */
}
/* Scroll the viewport text down one line, then copy the
* associated text for the top line from the buffer to the
* viewport.
*/
if( !this->update )
{
if(vrow >= v_nrows(v)-1) /* Old line is gone */
b_gotorc(b, this->row_off + v_nrows(v)-1, bcol);
else
b_gotorc(b, brow, bcol );
}
else
{
v_scroll(v, -1, 0); /* scroll down 1 line */
v_gotorc(v, 0, 0); /* first line, col. 0 */
for(i = v_ncols(v); --i >= 0 ;) /* screen = buffer */
v_putc(v, *b_advance(b), 1 );
if(vrow >= v_nrows(v)-1) /* Old line is gone */
{
/* Can't restore old cursor position because the */
/* line's not there anymore. go to the original */
/* column, but of the new bottom line */
b_gotorc(b, this->row_off + v_nrows(v)-1, bcol);
v_gotorc(v, v_nrows(v)-1, vcol);
}
else /* Otherwise restore original cursor to be */
{ /* under original character */
b_gotorc(b, brow, bcol );
v_gotorc(v, vrow+1, vcol );
}
}
}
exit:
monitor(this, UPDATE);
return rv;
}
/*------------------------------------------------------------*/
int draw( win *const this, int ask_top, int ask_left )
{
/* Fill the viewport with text from the buffer, the viewport
* is at offset "top" from the top line of the buffer and
* "left" from the left edge of the buffer. Cursor doesn't
* move with respect to the viewport. Top and left are
* truncated if necessary to prevent the viewport from
* moving off the edge of the buffer. Return false if the
* coordinates were modified to draw things, true otherwise.
*/
viewport *const v = &this->v;
textbuf *const b = &this->b;
int col = 0;
int row = 0;
int nrows = v_nrows( v );
int ncols = v_ncols( v );
const int left = max(0, min(ask_left, b_ncols(b)-v_ncols(v)));
const int top = max(0, min(ask_top, b_nrows(b)-v_nrows(v)));
int cur_top = top;
int start_row = v_row(v);
int start_col = v_col(v);
if( !this->update ) /* no updating, pretend we succeeded */
return 1;
while( --nrows >= 0 )
{
/* both b_gotorc and v_gotorc have side effects */
b_gotorc( b, cur_top, left ); ++cur_top;
v_gotorc( v, row, 0 ); ++row;
for( col = ncols; --col> 0 ;) /* all but last char. */
v_putc(v, *b_advance(b), 1 );
v_putc(v, *b_current(b), 0 ); /* last character. */
}
this->row_off = top;
this->col_off = left;
v_gotorc(v, start_row, start_col );
b_gotorc(b, start_row + top, start_col + left );
monitor(this, UPDATE);
return( top == ask_top && left == ask_left );
}
/*------------------------------------------------------------*/
static int hscroll( win *const this, int left )
{
/* Scroll horizontally, "left" columns to the left (right if
* negative). There's no import/export feature here, so a
* scroll past the edge of the buffer is illegal. Return true
* if you moved the required number of columns, false if not.
* Note that there still might have been motion in the earlier
* case, just not enough of it. A request of zero columns
* to the left just does a redraw.
*/
return draw( this, this->row_off, this->col_off + left);
}
/*------------------------------------------------------------*/
int e_update( win *const this, int enable )
{
/* If "enable" is false, store a snapshot of the current
* viewport and file states. If it's true, attempt to restore
* previous state (cursor position and relative positions
* of the file, buffer, and viewport).
*
* This routine is meant primarily to disable screen updating
* while the file is being examined. Return 1 if you change
* state 1 if the current state is requested.
*/
if( this->update == enable ) /* nothing to do */
return 0;
if( !enable ) /* disabling */
{
this->update = 0;
this->update_row_off = this->row_off;
this->update_col_off = this->col_off;
this->update_file_off = this->file_off;
this->update_row = e_row(this);
this->update_col = e_col(this);
this->dirty = 0;
}
else /* enabling */
{
/* Get the cursor back to the original place with
* an e_gotorc(), then scroll the screen as necessary
* to get the cursor positioned correctly relative to
* the viewport.
*/
e_gotorc( this, this->update_row, this->update_col );
while( this->file_off < this->update_file_off )
if( !e_vscroll(this, 1, 1) )
break;
while( this->file_off > this->update_file_off )
if( !e_vscroll(this, 0, 1) )
break;
while( this->row_off < this->update_row_off )
if( !e_vscroll(this, 1, 1) )
break;
while( this->row_off > this->update_row_off )
if( !e_vscroll(this, 0, 1) )
break;
this->update = 1;
if( this->col_off != this->update_col_off )
fprintf(stderr,"INTERNAL WINDOW ERROR: "
"unexpected horiz motion\n");
if( this->dirty )
draw( this, this->row_off, this->col_off );
}
monitor(this, UPDATE);
return 1;
}
/*------------------------------------------------------------*/
int e_gotorc( win *const this, int dst_r, int dst_c )
{
/* Go to the indicated virtual row and column. If r and c
* are inside the viewport, just go there. If not, scroll
* the viewport as appropriate. New lines are imported if
* you request a row address that is not in the buffer.
* Note that this subroutine might be used to add lines to
* the end of the file (by going down from the last line).
*/
viewport *const v = &this->v;
textbuf *const b = &this->b;
int rv = 1; /* return value */
int r, c;
int nrows = v_nrows( v );
int ncols = v_ncols( v );
switch( dst_r )
{
case E_HOME: dst_r = this->row_off; break;
case E_MID: dst_r = this->row_off + nrows/2; break;
case E_LAST: dst_r = this->row_off + nrows-1; break;
}
r = dst_r;
if( !(0 <= dst_c && dst_c < b_ncols(b)) || r < 0 )
{
rv = 0; // Illegal address
goto exit;
}
c = dst_c;
/* Get the desired column into the viewport, starting with
* column index:
* Modify c to hold the distance that c is from the right
* of the viewport. For example, c will be 0 if it's
* the first column past the one in the right edge of the
* viewport. If c is -1, it's at the right edge of the
* viewport. If it's -ncols then it's at the left edge of
* the viewport. Then, scroll as necessary to get c into
* the viewport.
*/
c -= this->col_off + ncols;
if( c >= 0 )
{
while( c-- >= 0 )
if( !hscroll(this, 1) ) /* scroll left */
{
rv = 0;
goto exit;
}
}
else if( c < -ncols )
{
c += ncols; /* c = -1 ==> 1 col to left of viewport. */
while( ++c <= 0 )
if( !hscroll(this, -1) ) /* scroll right */
{
rv = 0;
goto exit;
}
}
/* Do the same thing with the vertical coordinate. The
* situation is more complicated here, though, because the row
* coordinate is file relative. In other words:
*
* r == file_off + row_off + v_row(v)
*
* After the subtract, below, r will hold the distance between
* the top of the viewport and the desired row, negative if
* the desired row is above the viewport.
*/
r -= this->row_off + this->file_off;
if( r < 0 ) /* desired row is above viewport */
{
while( ++r <= 0 )
if( !e_vscroll(this, -1, 1) ) /* scroll text down */
{
rv = 0;
goto exit;
}
}
else if( r >= nrows )
for( r -= (nrows-1); --r >= 0 ;)
if( !e_vscroll(this, 1,1) ) /* scroll text up */
{
rv = 0;
goto exit;
}
/* the desired cursor is now in the viewport. Go there. */
b_gotorc(b, dst_r - this->file_off, dst_c);
if( this->update )
v_gotorc(v, dst_r - this->row_off - this->file_off,
dst_c - this->col_off );
exit:
monitor(this, UPDATE);
return rv;
}
/*------------------------------------------------------------*/
static int bottom(win *const this, int offset )
{
/* if offset isn't zero, set bottom to it's current
* value + offset, otherwise set it to the current line.
*/
if( !offset )
{
int lineno = b_row(&this->b) + this->file_off;
if( lineno > this->bottom )
this->bottom = lineno;
}
else if( (this->bottom += offset) < -1 )
this->bottom = -1;
return this->bottom;
}
/*------------------------------------------------------------*/
void e_replace (win *const this,int c)
{
bottom(this,0);
if( c )
{
this->dirty = 1;
if( this->update )
v_putc( &this->v, c, 0 );
*b_current(&this->b) = c;
}
monitor(this, UPDATE);
}
/*------------------------------------------------------------*/
void e_ins(win *const this, int c )
{
viewport *const v = &this->v;
bottom(this,0);
b_insert_c( &this->b, 1, c ? c : ' ');
this->dirty = 1;
if( this->update )
{
v_scroll_region( v, 0, -1, v_col(v), v_row(v),
v_ncols(v)-1, v_row(v) );
v_putc( v, c ? c : ' ', 0 );
}
monitor(this, UPDATE);
}
/*------------------------------------------------------------*/
void e_del(win *const this)
{
viewport *const v = &this->v;
textbuf *const b = &this->b;
int vrow = v_row(v);
int vcol = v_col(v);
int brow = b_row(b);
int bcol = b_col(b);
b_delete_c( &this->b, 1, ' ' );
this->dirty = 1;
if( this->update )
{
v_scroll_region( v, 0, 1, v_col(v), v_row(v),
v_ncols(v)-1, v_row(v) );
v_gotorc (v, vrow, v_ncols(v)-1);
}
b_gotorc (b, brow, (v_ncols(v)-1) + this->col_off);
if( this->update )
{
v_putc (v, *b_current(b), 0);
v_gotorc (v, vrow, vcol);
}
b_gotorc(b, brow, bcol);
monitor(this, UPDATE);
}
/*------------------------------------------------------------*/
int e_closeline(win *const this)
{
viewport *const v = &this->v;
textbuf *const b = &this->b;
int ecol = e_col(this); /* absolute row and column */
int erow = e_row(this);
char *new;
int i, bottom_line_of_buffer;
if( this->bottom < 0 )
return 0;
b_gotorc ( b, b_row(b), 0 );
del_line ( this, b, this->file_off + b_row(b) );
this->dirty = 1;
b_closedown( b, ' ');
if( this->update )
v_scroll_region( v, 1, 0, 0, v_row(v), v_ncols(v)-1,
v_nrows(v)-1 );
bottom(this, -1); /* Bottom line moves up one notch
* because of the delete.
*/
/* Import a new bottom line into the buffer if there's an
* import function and there is text in the file below the
* bottom line of the buffer.
*
* Note that since we just deleted a buffer line, all of the
* file-relative line numbers have changed, so the line being
* imported is actually the last line in the buffer, not the
* line below the last line as was the case in the vertical-
* scroll function.
*/
bottom_line_of_buffer = this->file_off + b_nrows(b) - 1;
if( this->import && this->bottom > bottom_line_of_buffer )
{
if(new = (*this->import)(this, bottom_line_of_buffer) )
{
/* Move the imported line into the buffer */
b_gotorc(b, b_nrows(b)-1, 0 );
for( i = b_ncols(b); --i >= 0 && *new ;)
*b_advance(b) = *new++;
}
}
/* If original row is now off the bottom of the file,
* adjust it down to compensate.
*/
if( erow > this->bottom )
erow = this->bottom < 0 ? 0 : this->bottom ;
/* Update the viewport to display the imported line
*/
if( this->update )
{
b_gotorc(b, v_nrows(v)-1 + this->row_off, this->col_off );
v_gotorc(v, v_nrows(v)-1, 0 );
for( i = v_ncols(v); --i >= 0; v_putc(v,*b_advance(b),1) )
;
}
e_gotorc(this, erow, ecol );
e_gotorc(this, e_row(this), e_first(this) );
monitor(this, UPDATE);
return 1;
}
/*------------------------------------------------------------*/
int e_openline(win *const this, int below)
{
/* open the line on which the cursor is resting by moving all
* following lines down a notch and importing a blank line.
* If below is true, open the line beneath the current one.
* Cursor ends up at far left of new line.
*/
textbuf *b = &this->b;
viewport *v = &this->v;
int line = e_row(this);
int scrolled = 0;
int row;
this->dirty = 1;
if( below )
{
/* If we're inserting below the last line of the file, and
* the cursor's resting on the bottom line of both the
* viewport and the buffer, force a scroll up without
* importing. In any event, adjust the target line to be
* the one beneath the current on.
*/
if( (line == this->bottom) && v_ateob(v) && b_ateob(b) )
scrolled = e_vscroll( this, 1, 0 );
++line;
}
e_gotorc(this, line, 0); /* go to line that will be replaced */
/* export the bottom line of the buffer if it has something
* in it
*/
if( this->bottom >= b_nrows(b)-1 && !scrolled )
{
row = b_row(b);
b_gotorc (b, b_nrows(b)-1, 0);
export (this, b, this->file_off + b_row(b) );
b_gotorc (b, row, 0);
}
/* Scroll everything below current line down a notch and
* put cursor at start of new line.
*/
b_opendown(b,' ');
if( this->update )
v_scroll_region(v, -1, 0, 0, v_row(v), v_ncols(v)-1,
v_nrows(v)-1 );
e_gotorc(this, line, 0);
/* Update file size and tell file-manager to insert line at
* current position
*/
bottom(this, +1); /* update the file size */
return (this->insert) ? (*this->insert)( this, line ) : 1 ;
}
/*------------------------------------------------------------*/
void e_cleartoeol( win *const this )
{
this->dirty = 1;
b_cleartoeol( &this->b,' ');
if( this->update )
v_cleartoeol( &this->v );
monitor(this, UPDATE);
}